/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import {useContext, useEffect, useRef, useState} from 'react';
import {Dimensions} from 'react-native';
import {
  Camera as VisionCamera,
  useCameraDevice,
  useCameraFormat,
  useCameraPermission,
} from '@react-native-oh-tpl/react-native-vision-camera';
import Context from '../../Context';
import {emitter} from '../../EventEmitter';
import type {ActionType} from '../../EventEmitter/types';
import {useIsForeground} from '../../hooks/useIsForeground';
import {useIsFocused} from '@react-navigation/core';
import {useBreakpointValue, useHeightBreakpointValue} from '@hadss/react_native_adaptive_layout';
import {CameraRoll} from '@react-native-camera-roll/camera-roll';
import Orientation from '@react-native-oh-tpl/react-native-orientation-locker';

/**
 * @description 相机组件
 * @returns
 */
const Camera = (props): JSX.Element => {
  const {isOpenVideo = false, isOpenPhoto = true} = props;
  const {width, height} = Dimensions.get('window');
  const [pending, setPending] = useState<boolean>(false);
  const camera = useRef<VisionCamera>(null);
  const {position, setPath, setIsRecording, setPosition, setMediaType, mode} = useContext(Context);
  const {hasPermission, requestPermission} = useCameraPermission();
  const isSmall = useBreakpointValue<boolean>({
    base: true,
    sm: true,
    md: false,
    lg: false,
  });
  const isMedium = useHeightBreakpointValue<boolean>({
    base: false,
    sm: false,
    md: true,
    lg: false,
  });

  let device = useCameraDevice(position);

  const format = useCameraFormat(device, [
    {fps: 60},
    {videoAspectRatio: isSmall && isMedium ? 1 : 16 / 9},
    {videoResolution: 'max'},
    {photoAspectRatio: isSmall && isMedium ? 1 : 4 / 3},
    {photoResolution: 'max'},
  ]);

  const isFocussed = useIsFocused();
  const isForeground = useIsForeground();
  const isActive = isForeground && isFocussed && !pending;

  useEffect(() => { 
    const setupOrientation = async (): Promise<void> => {
      if (isSmall) {
        await Orientation.lockToPortrait(); 
      } else {
        await Orientation.unlockAllOrientations();
      }
    };
    setupOrientation();
    return () => {
      Orientation.unlockAllOrientations();
    };
  }, [isSmall]); 

  const handleAction = async (data?: ActionType): Promise<void> => {
    if (data === 'take_photo') {
      const photoFile = await camera?.current?.takePhoto();
      setPath({uri: `file://${photoFile?.path}`});
      setMediaType('photo');
      CameraRoll.saveAsset(photoFile?.path);
    }
    if (data === 'start_record') {
      setIsRecording(true);
      await camera?.current?.startRecording({
        flash: 'off',
        videoBitRate: 'extra-low',
        videoCodec: 'h265',
        onRecordingFinished: video => {
          setPath({uri: `file://${video.path}`});
          setMediaType('video');
          CameraRoll.saveAsset(video.path);
        },
        onRecordingError(error) {
          console.log(error);
        },
      });
    }
    if (data === 'stop_record') {
      setIsRecording(false);
      await camera?.current?.stopRecording();
    }
    if (data === 'switch') {
      setPosition(pre => (pre === 'back' ? 'front' : 'back'));
    }
  };
  useEffect(() => {
    emitter.subscribe<ActionType>('camera:action', handleAction);
    return (): void => {
      emitter.unsubscribe('camera:action', handleAction);
    };
  }, []);

  useEffect(() => {
    if (!hasPermission) {
      requestPermission().then(() => {
        handleChange();
      });
    }
  }, []);

  const setStatus = (): Promise<void> => {
    setPending(true);
    return new Promise(resolve => {
      setTimeout(() => {
        resolve();
      }, 300);
    });
  };

  const handleChange = (): void => {
    setStatus().then(() => {
      if (device == null) {
        setPosition(pre => (pre === 'back' && isSmall && isMedium ? 'front' : 'back'));
        setStatus().then(() => {
          setPending(false);
        });
      } else {
        setPending(false);
      }
    });
  };

  useEffect(() => {
    handleChange();
  }, [width, height]);

  return (
    <VisionCamera
      ref={camera}
      device={device!}
      isActive={isActive}
      isMirrored={false}
      video={isOpenVideo}
      photo={isOpenPhoto}
      videoAspectRatio={16 / 9}
      photoAspectRatio={4 / 3}
      audio={true}
      resizeMode="cover"
      videoHdr={false}
      style={{
        aspectRatio: mode === 'photo' ? 3 / 4 : 9 / 16,
        overflow: 'hidden',
      }}
    />
  );
};

export default Camera;
